<?php

namespace july\julyadmin\builder\table;

use july\julyadmin\builder\traits\actions\HasBase;

/**
 * 表格搜索表單
 * @author July
 */
class Search
{
    use HasBase;
    //所属表格id
    private $tableId = '';
    //工具栏html
    private $html = '';
    //工具栏script
    private $script = '';
    //设置列宽
    //col-*：在所有视口宽度尺寸上等分列宽。
    //col-sm-*：在视口宽度尺寸大于等于576px时等分列宽，如果尺寸小于576px，则列堆叠在一起，即每个列占据整行的宽度。
    //col-md-*：在视口宽度尺寸大于等于768px时等分列宽，如果尺寸小于768px，则列堆叠在一起，即每个列占据整行的宽度。
    //col-lg-*：在视口宽度尺寸大于等于992px时等分列宽，如果尺寸小于992px，则列堆叠在一起，即每个列占据整行的宽度。
    //col-xl-*：在视口宽度尺寸大于等于1200px时等分列宽，如果尺寸小于1200px，则列堆叠在一起，即每个列占据整行的宽度。
    //col-xxl-*：在视口宽度尺寸大于等于1400px时等分列宽，如果尺寸小于1400px，则列堆叠在一起，即每个列占据整行的宽度。
    private $col = 'col-sm-6 col-md-6 col-lg-4 col-xl-4 col-xxl-3';
    //表单元素
    private $forms = [];
    //label标签宽度
    private $labelWidth = 5;
    //input位置宽度
    private $inputWidth = 7;
    //h5表单元素列表
    private $h5inputs = ['text', 'date', 'datetime-local', 'month', 'time', 'week'];
    //表格类型
    protected $tableType = 'table';

    /**
     * 设置表格类型
     * @param string $type 表格类型table,treeTable
     * @return  this
     */
    public function tableType($type = 'table')
    {
        $this->tableType = $type;
        return $this;
    }

    /**
     * 绑定表格id
     * @param $tableId  表格id，自己定义\
     */
    public function bindTableId($tableId = '')
    {
        $this->tableId = $tableId;
        return $this;
    }

    /**
     * 添加搜索文组件
     * @param  string $field          字段
     * @param  string $label          名称
     * @return this
     */
    public function show($type = 'text', $field = '', $label = '')
    {
        $form              = new \stdClass();
        $form->type        = $type;
        $form->field       = $field;
        $form->label       = $label;
        $form->placeholder = $label;
        //内容
        $form->value = '';
        if ($type == 'select') {
            //select下拉数据
            $form->options = [];
            //ajax获取数据url,当options为空生效
            $form->dataUrl = '';
            //ajax获取数据每页多少条
            $form->rows = 10;
            //是否多选
            $form->multiple = false;
        }
        $this->forms[] = $form;
        return $this;
    }

    /**
     * 设置下拉每页条数
     * @param integer $total 条数
     * @return this
     */
    public function setSelectPageTotal($total = 10)
    {
        if ($this->forms[count($this->forms) - 1]->type == "select") {
            $this->forms[count($this->forms) - 1]->rows = $total;
        } else {
            throw new \Exception("组件：" . $this->forms[count($this->forms) - 1]->type . "不支持此方法！");
        }
        return $this;
    }

    /**
     * 设置select请求地址
     * @param  string $url 请求地址
     * @return this
     */
    public function dataUrl($url = "")
    {
        if ($this->forms[count($this->forms) - 1]->type == "select") {
            $this->forms[count($this->forms) - 1]->dataUrl = is_string($url) ? $url : (string) $url;
        } else {
            throw new \Exception("组件：" . $this->forms[count($this->forms) - 1]->type . "不支持此方法！");
        }
        return $this;
    }

    /**
     * 设置placecholder
     * @param  string $placeholder
     * @return this
     */
    public function placeholder($placeholder = '')
    {
        $this->forms[count($this->forms) - 1]->placeholder = $placeholder;
        return $this;
    }

    /**
     * 设置列数
     * col-*：在所有视口宽度尺寸上等分列宽。
     * col-sm-*：在视口宽度尺寸大于等于576px时等分列宽，如果尺寸小于576px，则列堆叠在一起，即每个列占据整行的宽度。
     * col-md-*：在视口宽度尺寸大于等于768px时等分列宽，如果尺寸小于768px，则列堆叠在一起，即每个列占据整行的宽度。
     * col-lg-*：在视口宽度尺寸大于等于992px时等分列宽，如果尺寸小于992px，则列堆叠在一起，即每个列占据整行的宽度。
     * col-xl-*：在视口宽度尺寸大于等于1200px时等分列宽，如果尺寸小于1200px，则列堆叠在一起，即每个列占据整行的宽度。
     * col-xxl-*：在视口宽度尺寸大于等于1400px时等分列宽，如果尺寸小于1400px，则列堆叠在一起，即每个列占据整行的宽度。
     * @param  integer $count 列数，如"col-sm-3 col-md-4"
     * @return this
     */
    public function col($col = '')
    {
        $this->col = $col;
        return $this;
    }

    /**
     * 设置label标签宽度和input位置宽度
     * @Author   July
     * @DateTime 2023-11-22T19:27:33+0800
     * @param    integer                  $labelWidth 标签宽度，1-12的值
     * @param    integer                  $inputWidth input位置宽度，1-12的值
     * @return   this
     */
    public function size($labelWidth = 4, $inputWidth = 8)
    {
        if (!$labelWidth || !is_numeric($labelWidth) || $labelWidth <= 0 || $labelWidth > 12) {
            throw new \Exception("labelWidth只能是1-12的值！");
        }
        if (!$inputWidth || !is_numeric($inputWidth) || $inputWidth <= 0 || $inputWidth > 12) {
            throw new \Exception("inputWidth只能是1-12的值！");
        }

        $this->labelWidth = $labelWidth;
        $this->inputWidth = $inputWidth;
        return $this;
    }

    /**
     * 设置step，当input type=datetime-local生效
     * @param  boolean $show 是否显示
     * @return this
     */
    public function setStep($show = true)
    {
        if ($show) {
            if ($this->forms[count($this->forms) - 1]->type == "datetime-local") {
                $this->forms[count($this->forms) - 1]->step = 1;
            } else {
                throw new \Exception("组件：" . $this->forms[count($this->forms) - 1]->type . "不支持此方法！");
            }
        }

        return $this;
    }
    /**
     * 设置select 数据
     * @param  array $options 下拉数据，键值对数组
     * @return this
     */
    public function options($options = [])
    {
        if ($this->forms[count($this->forms) - 1]->type == "select") {
            $this->forms[count($this->forms) - 1]->options = $options;
        } else {
            throw new \Exception("组件：" . $this->forms[count($this->forms) - 1]->type . "不支持此方法！");
        }
        return $this;
    }

    /**
     * 设置select 是否多选
     * @param  boolean $multiple 多选是否开启
     * @return this
     */
    public function multiple($multiple = true)
    {
        if ($this->forms[count($this->forms) - 1]->type == "select") {
            $this->forms[count($this->forms) - 1]->multiple = $multiple;
        } else {
            throw new \Exception("组件：" . $this->forms[count($this->forms) - 1]->type . "不支持此方法！");
        }
        return $this;
    }
    /**
     * 设置搜索表单默认值
     * @param  string $value 默认值
     * @return this
     */
    function default($value = '') {
        $this->forms[count($this->forms) - 1]->value = $value;
        return $this;
    }
    /**
     * 渲染搜索表單
     */
    public function render()
    {
        $this->html = <<<EOT

                <form id="{$this->tableId}-search-form" class="row p-1" method="post" role="form" onsubmit="tableSearch(this);return false">
EOT;
        foreach ($this->forms as $k => $v) {
            $this->html .= <<<EOT

                    <div class="row {$this->col} p-2 search-form-item-{$v->field}">
                        <label class="col-sm-{$this->labelWidth} col-form-label text-sm-end text-md-end text-lg-end text-xl-end pe-2">{$v->label}</label>
                        <div class="col-sm-{$this->inputWidth}">
EOT;
            //处理普通表单h5组件
            if (in_array($v->type, $this->h5inputs)) {
                $step = $v->type == "datetime-local" && isset($v->step) ? "step=" . $v->step . " " : "";
                $this->html .= <<< EOT

                        <input type="{$v->type}" {$step} class="data-theme form-control pull-left" id="search-form-{$v->field}" name="search[{$v->field}]" placeholder="{$v->placeholder}" value="{$v->value}"/>
EOT;
            }

            //处理select2组件
            if ($v->type == 'select') {
                $multiple    = $v->multiple ? 'multiple="multiple"' : '';
                $is_multiple = $v->multiple ? '[]' : '';
                $this->html .= <<<EOT
                        <select class="data-theme form-control" lay-ignore id="search-form-{$v->field}" name="search[{$v->field}]{$is_multiple}" {$multiple}>
                        </select>
EOT;
            }

            $this->html .= <<<EOT

                        </div>
                    </div>
EOT;
        }
        $this->html .= <<<EOT

                        <div class="col-sm-2 p-2">
                        <button type="button" onclick="tableSearch(this)" style="margin:4px;margin-left:0px;" class="btn btn-sm btn-primary mdi mdi-tag-search">搜索</button>
                        <button type="button" onclick="clearSearchForm(this)" class="btn btn-sm btn-warning mdi mdi-delete-empty">重置</button>
                    </div>
                </form>
EOT;

        $forms        = json_encode($this->forms, JSON_UNESCAPED_UNICODE);
        $this->script = <<<EOT
        <script>
            function initializeSelect2(){
                //处理select2组件
                var forms = {$forms};
                forms.map((item,index)=>{
                    if(item.type=="select"){
                        if(item.dataUrl!=''){
                            var select2_config = {
                                ajax : {
                                    url : item.dataUrl,
                                    dataType : 'json',
                                    //延迟显示
                                    delay : 250,
                                    data : function(params) {
                                        return {
                                            //搜索框内输入的内容，传递到后端的parameter为keyword
                                            keyword : params.term,
                                            //第几页
                                            page : params.page,
                                            //每页显示多少行
                                            rows : item.rows
                                        };
                                    },
                                    //分页
                                    processResults : function(data, params) {
                                        params.page = params.page || 1;
                                        return {
                                            //后台返回的数据集
                                            results : data.data,
                                            pagination : {
                                                //总页数为10，那么1-9页的时候都可以下拉刷新
                                                more : params.page < Math.ceil(data.total/item.rows)
                                            }
                                        };
                                    },
                                    cache : false
                                }
                            };
                        }else if(item.type=="select" && item.dataUrl==''){
                            var data = [];
                            Object.keys(item.options).forEach((key) => {
                                data.push({
                                    id:key,
                                    text:item.options[key]
                                });
                            })
                            var select2_config = {
                                data:data
                            };
                        }
                        $("#search-form-"+item.field).select2({
                            //指定语言为中文，国际化才起效
                            language : "zh-CN",
                            multiple :item.multiple,
                            allowClear:true,
                            closeOnSelect:!item.multiple,
                            placeholder:item.placeholder,
                            placeholderOption:"first",
                            ...select2_config,
                            escapeMarkup : function(markup) {
                                return markup;
                            },
                            templateSelection : function(repo) {
                                //列表中选择某一项后显示到文本框的内容
                                return repo.text;
                            }
                        }).on('select2:open', function(e) {
                            //展开时搜索框获取焦点
                            const selectId = e.target.id;
                            setTimeout(function(){
                                $(".select2-search__field[aria-controls='select2-"+selectId+"-results']").each(function (key,value,){
                                    value.focus();
                                });
                            },100);
                        });

                        //如果有默认值，那么加载出来，并且选择上
                        if(item.value && item.dataUrl){
                            $.ajax({
                                type:'GET',
                                url:item.dataUrl,
                                data:{default:item.value},
                                dataType:'json',
                                success:function(res) {
                                    if(res.hasOwnProperty("data")){
                                        res.data.map((select_data_item,select_data_index)=>{
                                            $("#search-form-"+item.field).append('<option selected value="' + select_data_item.id + '">' + select_data_item.text + '</option>');
                                        });
                                    }
                                    $("#search-form-"+item.field).val(new String(item.value).split(",")).trigger("change");
                                },
                                error:function(res){
                                    layer.msg(JSON.stringify(res),{
                                        icon:5,
                                        time:2000,
                                        shade:[0.6,'#000',false]
                                    });
                                }
                            });
                        }else if(item.value && !item.dataUrl){
                            $("#search-form-"+item.field).val(new String(item.value).split(",")).trigger("change");
                        }else{
                            $("#search-form-"+item.field).val("").trigger("change");
                        }
                    }
                });
            }

            try {
                initializeSelect2();
            } catch (e) {

            }

            //搜索
            function tableSearch(that){
                //表格重新加载，并且带上搜索参数
                layui.{$this->tableType}.reloadData('{$this->tableId}',{
                    where:getSearchParams(),
                    page: {
                        curr: 1
                    }
                });
            }

            //获取搜索条件
            function getSearchParams(){
                var queryParams = new Object();
                $.each($("#{$this->tableId}-search-form").serializeArray(), function() {
                    if(this['name'].indexOf("[]")>-1){
                        if(queryParams.hasOwnProperty(this['name'].replace("[]",""))){
                            queryParams[this['name'].replace("[]","")].push(this['value']);
                        }else{
                            queryParams[this['name'].replace("[]","")] = [];
                            queryParams[this['name'].replace("[]","")].push(this['value']);
                        }
                    }else{
                        queryParams[this['name']] = this['value'];
                    }

                    //如果当前组件存在，并且时下拉，并且是多选，把所选的值取出来弄成一维数组的形式放进去
                    if($("#{$this->tableId}-search-form").find("select[name='"+this['name']+"']").length>0){
                        if($("#{$this->tableId}-search-form").find("select[name='"+this['name']+"']").attr("multiple")=="multiple"){
                            if($("#{$this->tableId}-search-form").find("select[name='"+this['name']+"']").prop("outerHTML").indexOf("select2-hidden-accessible")>-1){
                                var select_data = $("select[name='"+this['name']+"']").select2("data");
                                var ids = [];
                                select_data.map(item=>{
                                    ids.push(item.id);
                                });
                                queryParams[this['name']] = ids;
                            }
                        }
                    }
                });
                return queryParams;
            }

            //清空搜索表单
            function clearSearchForm(that){
                var forms = {$forms};
                //清空搜索表单原生控件
                $("#{$this->tableId}-search-form")[0].reset();
                //清空搜索表单select2控件
                forms.map(item=>{
                    if(item.type=='select'){
                        if(item.value){
                            $("#search-form-"+item.field).val(new String(item.value).split(",")).trigger("change");
                        }else{
                            $("#search-form-"+item.field).val("").trigger("change");
                        }
                    }
                });
            }
        </script>
EOT;
        return ['html' => $this->html, 'script' => $this->script];
    }
}
